﻿#include "TraversalFiles.h"

TraversalFiles::TraversalFiles()
{

}


//遍历当前目录下的文件夹和文件,默认是按字母顺序遍历
bool TraversalFiles::TraverseFiles(string path,int &file_num)
{
    _finddata_t file_info;
    /*可以定义后面的后缀为*.exe，*.txt等来查找特定后缀的文件，*.*是通配符，
      匹配所有类型,路径连接符最好是左斜杠/，可跨平台*/
    string current_path = path+"/*.*";
    //打开文件查找句柄
    int handle = _findfirst(current_path.c_str(),&file_info);
    //返回值为-1则查找失败
    if(-1 == handle)
    {
        return false;
    }

    do
    {
        //判断是否子目录
        string attribute;
        if(file_info.attrib==_A_SUBDIR) //是目录
        {
            attribute = "dir";
        }
        else
        {
            attribute = "file";
        }
        /*输出文件信息并计数,文件名(带后缀)、文件最后修改时间、文件字节数(文件夹显示0)
        文件是否目录*/
        cout<<file_info.name<<' '<<file_info.time_write<<' '<<file_info.size<<' '<<attribute<<endl; //获得的最后修改时间是time_t格式的长整型，需要用其他方法转成正常时间显示
        file_num++;

    }while(!_findnext(handle,&file_info));  //返回0则遍历完

    //关闭文件句柄
    _findclose(handle);
    return true;
}

//深度优先递归遍历当前目录下文件夹和文件及子文件夹和文件
void TraversalFiles::DfsFolder(string path,int layer)
{
    _finddata_t file_info;
    string current_path = path+"/*.*"; //也可以用/*来匹配所有
    int handle=_findfirst(current_path.c_str(),&file_info);
    //返回值为-1则查找失败
    if(-1==handle)
    {
        cout<<"cannot match the path"<<endl;
        return;
    }

    do
    {
        //判断是否子目录
        if(file_info.attrib==_A_SUBDIR)
        {
            //递归遍历子目录
            //打印记号反映出深度层次
            for(int i = 0; i < layer; i++)
            {
                cout<<"--";
            }
            cout<<file_info.name<<endl;
            int layer_tmp = layer;
            //.是当前目录，..是上层目录，必须排除掉这两种情况
            if(strcmp(file_info.name,"..") != 0
                    &&strcmp(file_info.name,".") != 0)
            {
                //再windows下可以用\\转义分隔符，不推荐
                DfsFolder(path+'/'+file_info.name,layer_tmp+1);
            }
        }
        else
        {
            //打印记号反映出深度层次
            for(int i = 0; i < layer; i++)
            {
                cout<<"--";
            }
            cout<<file_info.name<<endl;
        }
    }while(!_findnext(handle,&file_info));  //返回0则遍历完
    //关闭文件句柄
    _findclose(handle);
}
/**
  * @brief 用队列遍历指定目录下的所有子目录和文件
*/
bool TraversalFiles::TraverseFilesWithQueue(string strPath)
{
    queue<string> tmpQueue;
    tmpQueue.push(strPath);
    _finddata_t file_info;

    while (tmpQueue.size() > 0)
    {
        string curPath = tmpQueue.front();
        string filter;
        int handle=_findfirst(filter.assign(curPath).append("/*.*").c_str(),&file_info);
        if(-1 == handle)
        {
            cout<<"cannot match the path"<<endl;
            tmpQueue.pop();
            continue;
        }

        do{
            if(file_info.attrib == _A_SUBDIR)
            {
                if(strcmp(file_info.name,"..") == 0
                        || strcmp(file_info.name,".") == 0)
                {
                    continue;
                }
                string nextPath = curPath + "/" + file_info.name;
                tmpQueue.push(nextPath);
            }
            else
            {
                cout<<curPath<<"   --: "<<file_info.name <<endl;
            }
        }
        while(!_findnext(handle,&file_info));
        tmpQueue.pop();
    }
    return true;
}

